Skip to content

improvement(workflow): polish canvas interactions and execution states - #5976

Open
andresdjasso wants to merge 7 commits into
stagingfrom
workflow-updates
Open

improvement(workflow): polish canvas interactions and execution states#5976
andresdjasso wants to merge 7 commits into
stagingfrom
workflow-updates

Conversation

@andresdjasso

@andresdjasso andresdjasso commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Unifies workflow cards, notes, and loop containers around the same border, action-swell, selected, disabled, and locked-state language.
  • Replaces estimated per-node progress with a branded indeterminate loader that remains smooth for millisecond workflows and stops immediately with the run.
  • Adds an on-canvas connected-block selector with correct filtering, loop-aware placement/focus, integration colors, and top/bottom edge fades.
  • Restores semantic block titles and provider/type tags, including Gmail and Human defaults.
  • Bounds long workflow notes to an independently scrollable preview with the same edge-gradient treatment as the selector.

What changed

Cards and execution

  • Keeps the action swell at a stable width so Run, Stop, and loader state changes do not shift the card or panel controls.
  • Removes connector pulses, execution-only outline thickening, icon flashes, and progress-mask seams.
  • Uses one indeterminate segmented animation for all active workflow nodes instead of trying to predict each node's duration.
  • Clears loader and hover/action-menu state immediately when a run stops or completes.
  • Moves disabled/locked state icons beside the type tag, fixes lock/unlock semantics, and keeps state hover styling stable.

Information hierarchy and tags

  • Uses operation names as default titles (Send Email, Wait for Input) while preserving provider/type tags and internal unique block names.
  • Restores integration brand fills across cards, selectors, previews, and the editor while retaining the native Sim palette.
  • Keeps native color assignments intentional: API uses blue, Router uses orange, and Loop uses graphite with white icon/text.

Loop containers

  • Rebuilds loops with the workflow-card border/action-swell language, matched stroke weight, a lighter interior, and correctly aligned input/output swells.
  • Gives the loop Start item its own output swell and preserves placement/focus inside the loop when creating a connected block.
  • Fits and centers the entire loop on selection rather than zooming into one corner.
  • Prevents parent and child action swells from appearing together and replaces the blue drag/drop highlight with a graphite outline that follows the loop's 16px corner radius.

Connected block selector and notes

  • Replaces the detached add-block flow with an on-canvas selector positioned at the connection release point.
  • Fixes relevant-result filtering/scrolling and uses a seamless surface with compact search spacing and top/bottom gradient fades.
  • Caps populated notes at 216px, provides a 176px keyboard-focusable scroll region, and keeps renderer/autolayout geometry consistent.
  • Notes retain the normal action swell but intentionally expose no connector affordances.

Type of Change

  • Bug fix
  • New feature
  • Improvement
  • Breaking change

Testing

  • Manually verified in the local workflow preview, including loader stop behavior, loop focus/hover, connected-block creation, selector scrolling, and long-note scrolling.
  • 9 focused Vitest files / 48 tests passed.
  • @sim/workflow-renderer and sim type checks passed after syncing dependencies to the rebased lockfile.
  • Lint completed; Biome reported its existing parser panic in the unrelated terminal session file but returned success and changed no files.
  • Monorepo boundaries, strict API validation, utils, Zustand, React Query, client boundary, icon, realtime-prune, skills, and agent-stream documentation audits passed.

Checklist

  • Code follows project conventions and uses local component styling.
  • Tests were added or updated and are passing.
  • The branch is rebased on the latest staging.
  • Local screenshots, QA artifacts, plans, environment backups, and installed design skills were excluded from the PR.

@andresdjasso
andresdjasso requested a review from a team as a code owner July 27, 2026 17:37
@cursor

cursor Bot commented Jul 27, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches realtime edge persistence, collaborative block error toggles, and immediate local cancel semantics alongside a large workflow-editor UI refactor, so regressions could affect saved graphs or run/stop behavior even though changes are not in auth or billing.

Overview
Unifies workflow canvas visuals and interaction around shared border/action-swell language, neutral selection rings (--text-secondary), and edges that darken when an endpoint is selected or open in the editor—execution no longer drives its own green pulse or post-run success/error rings on blocks.

Cards and actions: ActionBar adds a swell variant (card-aligned silhouettes, indeterminate ThinkingLoader while running, delayed action reveal after stop). Horizontal port flipping is removed from the bar and block context menu. Panel Deploy and Run/Stop move to Chip controls with animated play/stop loader.

Block canvas content: Titles and type tags come from resolveCanvasBlockPresentation (operation-based defaults like “Send Email”). Collapsed blocks can show chip rows or natural-language sentences with inline value chips; empty subblock rows are hidden. Error output can be toggled on the card with collaborative UPDATE_ERROR_ENABLED persistence and automatic removal of error edges when disabled.

New connected-block flow: ConnectionBlockSelector is an on-canvas transient node (search, recents, popular blocks) wired through add-block-from-toolbar with pendingConnect. Notes use swell actions and getNoteBlockHeight; navbar glass reuses shared FROSTED_GLASS_SURFACE.

Realtime / execution: Edge inserts canonicalize source/target handles via normalizeWorkflowEdge* (including replace-state dedup). Cancel stops the local stream and clears executing state immediately, then requests server cancellation. Subflow drop highlighting only applies when re-parenting to a different container; execution routing respects positioned source handles for success vs error paths.

Reviewed by Cursor Bugbot for commit 7f6cc9c. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Canonicalizes workflow edge handles throughout realtime persistence.

  • Normalizes legacy positioned source and target handles before duplicate comparison and storage.
  • Applies canonicalization to single-edge, batch-edge, block-batch, auto-connect, and full-state replacement paths.
  • Removes logical duplicates during full-state replacement while preserving distinct semantic routing handles.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the previously reported realtime canonicalization gap is addressed across the applicable persistence paths.

Important Files Changed

Filename Overview
apps/realtime/src/database/operations.ts All relevant realtime edge persistence paths now canonicalize positioned handles, and duplicate checks normalize both candidate and existing edges.
packages/workflow-types/src/workflow.ts Shared source and target canonicalizers collapse legacy positional aliases while retaining distinct semantic routing handles.

Reviews (2): Last reviewed commit: "fix(workflow): canonicalize realtime edg..." | Re-trigger Greptile

Comment thread packages/workflow-types/src/workflow.ts
Comment thread apps/sim/lib/workflows/blocks/deterministic-dimensions.ts
Comment thread apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx
Comment thread apps/sim/stores/workflows/workflow/store.ts
Comment thread packages/workflow-renderer/src/workflow-block/source-handle.ts
andresdjasso and others added 4 commits July 31, 2026 23:34
Connection anchors: an output now always leaves a card from the right.
The cursor swell lets a drag start on any edge, but the left side is the
input, so anchoring an outgoing edge there drew a line out of the input
port and read as a second input. `normalizeCursorSourceHandleId` resolves
every drag to the right anchor, `normalizePositionedSourceHandleId`
collapses `source-left` alongside the legacy vertical anchors (so data
from the API, an older client, or a stale save self-heals on load), and
only the right-side source anchor is mounted.

Drops in `onConnectEnd` are always source -> target. The branch that
reversed the edge for a drag starting on an input could never run: the
`target` handle is `isConnectableStart={false}` and the positioned side
anchors are `isConnectable={false}`, so React Flow never reports an input
as a drag origin. Removed it and its now-unused imports.

A newly created block is centered once its node mounts and is measured,
so a card added from a drag-release, the block menu, or the toolbar is
never left off-screen or under the editor panel.

The editor panel's block icon uses the same type accent as the card's
badge instead of the block's legacy `bgColor`, which had left the panel
on the old per-integration brand colours.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Start card intermittently collapsed after load, squashing the
action-menu tab so its icon row sat over the card.

`.workflow-drag-handle` is the host the border renderer measures, and both
it and the header row took their height from `blockHeight && blockHeight >
0`. `blockHeight` comes from the deterministic-dimensions pass and is
already floored at MIN_PAINTED_HEIGHT (48), but it is absent on the first
frames — and with no floor the host collapsed to its natural content
height (25.5px for a header-only trigger, exactly the title's line box).
The border builds its perimeter from `host.offsetHeight`, so that window
painted a sub-floor card: too little straight edge remained on the
vertical runs for the action-menu tab, which collapsed into the corner
arcs. Whether you saw it depended purely on whether the dimension publish
had landed, which is why it reproduced on one workflow and not another.

Floor all three: the host, the header row (so `items-center` centres the
title and type tag rather than pinning them to the top), and the border's
own `offsetHeight` read.

Also raise ACTION_MENU_CONTENT_READY_THRESHOLD to 0.9. At 0.8 the 24px
icon row was revealed while the swell had only reached 22.4px of its 28px
— shorter than the row it contains. Secondary to the above, but a real
overflow window on its own. The test now pins the ratio rather than the
constant.

Tag palette moves to fixed brand values (hex, not derived oklch) with two
inks — #F8F8F8 on dark fills, #1A1A1A on light. Tones are renamed to match
what they render. `green` (2.55:1) and `orange` (3.15:1) sit under WCAG AA
against their paired ink; both are deliberate brand decisions and are
documented in the component.

Deploy and Run take two new Button variants rather than className
overrides, so `tertiary` stays green everywhere else.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview Aug 1, 2026 5:10am

Request Review

@andresdjasso andresdjasso changed the title improvement(workflow): redesigned block cards with edge-following connection swell improvement(workflow): polish canvas interactions and execution states Aug 1, 2026
@andresdjasso

Copy link
Copy Markdown
Contributor Author

@greptile

@andresdjasso

Copy link
Copy Markdown
Contributor Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7f6cc9c. Configure here.


logger.debug(`Updated block error output: ${payload.id} -> ${payload.errorEnabled}`)
break
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error toggle lost on replace

Medium Severity

UPDATE_ERROR_ENABLED persists errorEnabled into block data, but the client store only updates the top-level field and REPLACE_STATE rewrites blocks from block.data alone without merging that top-level value the way full saves do. After undo/redo or any replace-state, a later reload can drop an enabled error output that has no error edge yet.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7f6cc9c. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant